Scheda rapida Python-MIP
Questa scheda raccoglie in un unico posto tutto ciò che di Python-MIP serve nei laboratori e nella parte di programmazione dell’esame. Non introduce nulla di nuovo: ogni riga rimanda al capitolo in cui il costrutto è stato usato per la prima volta.
1. L’API essenziale#
| Che cosa | Codice | Note |
|---|---|---|
| importare | import mip |
su Colab prima !pip install mip |
| creare il modello | m = mip.Model() |
opzionale sense=mip.MAXIMIZE / mip.MINIMIZE |
| variabile continua | x = m.add_var() |
limiti predefiniti lb=0, ub=INF |
| variabile intera / binaria | m.add_var(var_type=mip.INTEGER) / mip.BINARY |
mip.CONTINUOUS è il default |
altri argomenti di add_var |
lb=, ub=, name= |
name rende leggibile la stampa dei vincoli |
| vincolo | m.add_constr(espr <= b) oppure m += espr <= b |
<=, >=, == (mai =) |
| somma di espressioni | mip.xsum(c[i]*x[i] for i in range(n)) |
accetta un generatore o una lista |
| obiettivo | m.objective = mip.maximize(espr) / mip.minimize(espr) |
uno solo, si assegna |
| risolvere | status = m.optimize() |
restituisce un OptimizationStatus |
| valore di una variabile | x.x |
solo dopo optimize() |
| valore dell’obiettivo | m.objective_value |
|
| lista dei vincoli, duali | m.constrs, con.pi |
il duale è lo shadow price del vincolo |
| lista delle variabili, costi ridotti | m.vars, v.rc |
m.vars[2] è la terza variabile creata |
| silenziare il solver | m.verbose = 0 |
utile nei cicli con molte risoluzioni |
Lo stato restituito da optimize() va controllato quando il modello potrebbe essere inammissibile: mip.OptimizationStatus.OPTIMAL indica che la soluzione è ottima, INFEASIBLE che non esistono soluzioni, UNBOUNDED che l’obiettivo può crescere senza limite. Leggere x.x su un modello inammissibile restituisce None.
2. Gli schemi che ricorrono#
Variabili indicizzate da un insieme di numeri consecutivi, in una lista (cap. 1):
x = [m.add_var(var_type=mip.INTEGER) for i in range(n)]Variabili indicizzate da coppie, o da un insieme qualunque, in un dizionario (cap. 2):
f = {(i,j): m.add_var() for (i,j) in A} # archi
x = {p: m.add_var() for p in P} # un sottoinsieme di indiciUna famiglia di vincoli, «per ogni »: un ciclo for con dentro una xsum sull’altro indice.
for j in range(n_component):
m.add_constr(mip.xsum(A[j][i]*x[i] for i in range(n_model)) <= b[j])Somme filtrate, per esempio il flusso uscente e quello entrante in un nodo:
mip.xsum(f[i,j] for j in V if (i,j) in A) - mip.xsum(f[j,i] for j in V if (j,i) in A) == b[i]Lettura di una soluzione binaria con una soglia, mai con == 1:
sol = [(i,j) for (i,j) in E if x[i,j].x > 0.5]Una funzione che risolve il modello per dati diversi, che restituisce modello, soluzione e obiettivo (cap. 3):
def solve(A, b, c):
m = mip.Model()
x = [m.add_var() for j in range(len(c))]
for i in range(len(b)):
m.add_constr(mip.xsum(A[i][j]*x[j] for j in range(len(c))) <= b[i])
m.objective = mip.maximize(mip.xsum(c[j]*x[j] for j in range(len(c))))
m.optimize()
return m, [v.x for v in x], m.objective_valueAggiungere vincoli a posteriori e riottimizzare (tagli di subtour elimination, cap. 2):
while esiste_un_vincolo_violato(sol):
m.add_constr(...)
m.optimize()Dati che vanno copiati prima di essere modificati: b3 = b[:] crea una copia; b3 = b crea solo un secondo nome per la stessa lista, e modificare b3 modifica anche b.
3. La scaletta di modellazione#
Da ripetere identica per ogni problema, prima di scrivere una riga di codice.
- Insiemi: di che cosa si parla (prodotti, risorse, nodi, archi, periodi). Ogni insieme diventa un
rangeo una lista. - Parametri: tutti i numeri del testo, e solo quelli, con l’indice giusto (, , ). Lettere iniziali dell’alfabeto.
- Variabili decisionali: che cosa si decide, con che indice e di che natura (continua, intera, binaria). Lettere finali dell’alfabeto.
- Obiettivo: una sola espressione lineare, da massimizzare o minimizzare.
- Vincoli: una famiglia per ogni «per ogni» del testo; per ognuna, quale indice è fissato e su quale corre la somma.
- Traduzione: dati,
Model(), variabili, vincoli, obiettivo,optimize(), stampa. Poi verifica a mano che la soluzione rispetti i vincoli.
4. Errori tipici#
| Sintomo | Causa probabile | Rimedio |
|---|---|---|
| la soluzione ha valori frazionari inattesi | manca var_type |
mip.INTEGER o mip.BINARY |
print(x) stampa un oggetto |
manca .x |
x.x, m.objective_value |
KeyError su x[i,j] |
la coppia non è nell’insieme degli archi, o è nell’ordine sbagliato | filtrare con if (i,j) in A, rispettare |
| la soluzione non cambia dopo una modifica | cella non rilanciata, o add_constr che aggiunge invece di sostituire |
modificare la cella originale, riavviare il kernel |
SyntaxError su un vincolo di uguaglianza |
= al posto di == |
== |
| soluzione ottima con subtour | mancano i tagli | separare e aggiungere i vincoli violati |
status non ottimale, x.x è None |
modello inammissibile (dati, nodo isolato) | controllare i dati e il grafo |
| il ciclo di tagli non termina | termine di destra del taglio troppo largo | usare len(cycle) - 1 |
5. Glossario#
| Termine | Significato |
|---|---|
| LP, ILP, MIP | programmazione lineare; con variabili intere; con variabili miste |
| variabile decisionale | quantità che il modello sceglie; continua, intera o binaria |
| parametro | dato numerico del problema, fissato prima della risoluzione |
| forma standard | |
| rilassamento continuo | lo stesso modello con le variabili intere rese continue; ottimo non peggiore |
| knapsack | scegliere oggetti di valore massimo entro una capacità; variabili binarie |
| flusso, conservazione | quantità sugli archi; in ogni nodo uscente meno entrante uguale a |
| cut set | lati con un solo estremo in |
| subtour, subtour elimination | ciclo parziale; vincolo che lo esclude, |
| separazione, taglio | trovare un vincolo violato e aggiungerlo al modello |
| vincolo attivo | soddisfatto con uguaglianza all’ottimo |
| variabile duale, shadow price | valore marginale di un’unità in più del termine di destra |
| costo ridotto | ; quanto deve cambiare perché entri in soluzione |
| pricing, generazione di colonne | aggiungere le colonne a costo ridotto positivo finché non ne restano |
| solver | il programma (CBC, per Python-MIP) che risolve il modello con simplesso e branch and bound |